﻿#region using statements

using System;
using System.Collections.Generic;
using System.Text;

#endregion

namespace NGen.Managers.Logging
{
	/// <summary>
	/// 	the different logging levels
	/// </summary>
	public enum LoggingLevel
	{
		NONE = 0,

		MINIMAL = 1,

		MAXIMUM = 2
	}

	public class ManagerLogs : IManagerLogs
	{
		#region local fields

		/// <summary>
		/// 	default directory to store the logfiles
		/// </summary>
		private const string mc_logDirectory = "Logs";

		/// <summary>
		/// 	maintain a list of all of the loggers
		/// </summary>
		private readonly Dictionary<Type, Logger> m_dLoggers = new Dictionary<Type, Logger>();

		/// <summary>
		/// 	the type used for the primary logfile
		/// </summary>
		private readonly Type m_primaryLogType = typeof(GameEngine);

		/// <summary>
		/// 	the global logging level
		/// </summary>
		private LoggingLevel m_loggingLevel;

		#endregion

		#region local methods

		/// <summary>
		/// 	create a logger of the specified type
		/// </summary>
		/// <param name = "p_loggerType">the logger type to creater</param>
		protected void CreateLogger(Type p_loggerType) {
			if(m_dLoggers.ContainsKey(p_loggerType)) {
				return; //return if logger exists
			}

			//construct the logfile name
			var logfile = new StringBuilder().Append(mc_logDirectory).Append('\\').Append(p_loggerType.Name).Append(".log").ToString();

			//add the logger to the dictionary
			m_dLoggers.Add(p_loggerType, new Logger(logfile, GlobalLoggingLevel));
		}

		#endregion

		#region IManagerLogs implementation

		/// <summary>
		/// 	the logging level with which new loggers will be assigned
		/// </summary>
		public LoggingLevel GlobalLoggingLevel {
			get { return m_loggingLevel; }
			set {
				m_loggingLevel = value;
				foreach(var logger in m_dLoggers.Values) {
					logger.CurrentLogLevel = value;
				}
			}
		}

		/// <summary>
		/// 	clears all of the open logfiles
		/// </summary>
		public void ClearAllLogs() {
			foreach(var logger in m_dLoggers.Values) {
				logger.ClearLog();
			}
		}

		/// <summary>
		/// 	close all log files
		/// </summary>
		public void Cleanup() {
			foreach(var logger in m_dLoggers.Values) {
				logger.Close();
			}
		}

		/// <summary>
		/// 	returns a specific logger, if it does not exist then one is created
		/// </summary>
		/// <typeparam name = "TLoggerType">the type of logger to create</typeparam>
		/// <returns>the logger specific</returns>
		public ILogger Log<TLoggerType>() {
			if(!m_dLoggers.ContainsKey(typeof(TLoggerType))) {
				CreateLogger(typeof(TLoggerType));
			}
			return m_dLoggers[typeof(TLoggerType)];
		}

		/// <summary>
		/// 	write a message to a specific logger, if it doesn't not exist then one is created
		/// </summary>
		/// <typeparam name = "TLoggerType">the logger to use</typeparam>
		/// <param name = "p_message">the message to write</param>
		/// <param name = "p_logLevel">the logging level</param>
		public void Log<TLoggerType>(string p_message, LoggingLevel p_logLevel = GameEngine.DefaultLoggingLevel) {
			if(!m_dLoggers.ContainsKey(typeof(TLoggerType))) {
				CreateLogger(typeof(TLoggerType));
			}
			m_dLoggers[typeof(TLoggerType)].Write(p_message, p_logLevel);

			//also log to the main logfile if value is set in the logger
			if(m_dLoggers[typeof(TLoggerType)].AlsoWriteToMainLog &&
			   typeof(TLoggerType) != m_primaryLogType) {
				GameEngine.Log(p_message, p_logLevel);
			}
		}

		#endregion
	}
}